package eu.catengine.common.handler;

import android.view.MotionEvent;
import eu.catengine.common.iface.IDisposable;
import eu.catengine.common.manager.SceneManager;
import eu.catengine.common.manager.ScreenManager;
import eu.catengine.primitive.Point;
import eu.catengine.scene.Scene;
import eu.catengine.scene.TouchPointer;

/**
 * Klasa służąca do obsługi zdarzeń na ekranie dotykowym.
 * 
 * @author mbienkowski
 */
public class TouchHandler implements IDisposable
{
    private final int mMaxPoints;
    private ScreenManager mScreenManager;
    private SceneManager mSceneManager;
    private Scene mActiveScene;
    private Point mCameraPoint;
    private TouchPointer[] mTouchPointers;
    private TouchPointer[] mHistoricalTouchPointers;

    private int mPid;
    private int mAction;
    private int mActionCode;

    /**
     * Konstruktor domyślny. <br>
     * Obiekt klasy jest <b>tworzony automatycznie</b> w klasie CatEngineCore. <br>
     * Nie należy wywoływać metody ręcznie.
     */
    public TouchHandler()
    {
	mMaxPoints = 10;
	mScreenManager = ScreenManager.getInstance();
	mSceneManager = SceneManager.getInstance();
	mTouchPointers = new TouchPointer[mMaxPoints];
	mHistoricalTouchPointers = new TouchPointer[mMaxPoints];

	for (int i = 0; i < mMaxPoints; i++)
	{
	    mTouchPointers[i] = new TouchPointer();
	    mHistoricalTouchPointers[i] = new TouchPointer();
	}
    }

    /**
     * Metoda wywyływania w momencie akcji na ekranie dotykowym.
     */
    public void TouchAction(MotionEvent motionEvent)
    {
	mAction = motionEvent.getAction();
	mActionCode = mAction & MotionEvent.ACTION_MASK;

	mActiveScene = mSceneManager.getActiveScene();
	mCameraPoint = mActiveScene.getCamera().getAnchorPoint();

	for (int i = 0; i < motionEvent.getPointerCount() && i < mMaxPoints; i++)
	{
	    mPid = motionEvent.getPointerId(i);

	    Point rawTouchPoint = new Point(motionEvent.getX(i), motionEvent.getY(i));
	    Point hudTouchPoint = mScreenManager.getHudPoint(rawTouchPoint);
	    Point sceneTouchPoint = mScreenManager.getScenePoint(mCameraPoint, rawTouchPoint);

	    mHistoricalTouchPointers[mPid] = mTouchPointers[mPid];
	    mTouchPointers[mPid] = new TouchPointer(mPid, rawTouchPoint, hudTouchPoint, sceneTouchPoint);
	}

	switch (mActionCode)
	{
	case MotionEvent.ACTION_DOWN:
	case MotionEvent.ACTION_POINTER_DOWN:
	    mPid = mAction >> MotionEvent.ACTION_POINTER_ID_SHIFT;
	    mActiveScene.onPointerDown(mTouchPointers[mPid]);
	    break;
	case MotionEvent.ACTION_MOVE:
	    for (int i = 0; i < motionEvent.getPointerCount(); i++)
	    {
		mPid = motionEvent.getPointerId(i);
		mActiveScene.onPointerMove(mTouchPointers[mPid], mHistoricalTouchPointers[mPid]);
	    }
	    break;
	case MotionEvent.ACTION_UP:
	case MotionEvent.ACTION_POINTER_UP:
	case MotionEvent.ACTION_CANCEL:
	case MotionEvent.ACTION_OUTSIDE:
	    mPid = mAction >> MotionEvent.ACTION_POINTER_ID_SHIFT;
	    mActiveScene.onPointerUp(mTouchPointers[mPid]);
	}
    }

    @Override
    public void dispose()
    {
	mScreenManager = null;
	mSceneManager = null;
	mActiveScene = null;
	mCameraPoint = null;
	mTouchPointers = null;
	mHistoricalTouchPointers = null;
    }
}
